package com.senlingspace.system.service.impl;

import java.time.format.DateTimeFormatter;
import java.util.Date;

import cn.hutool.core.thread.ThreadUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageInfo;
import com.google.common.base.Stopwatch;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.senlingspace.common.config.SenlingSpaceConfig;
import com.senlingspace.common.core.domain.AjaxResult;
import com.senlingspace.common.core.domain.entity.SysUser;
import com.senlingspace.common.core.domain.model.LoginUser;
import com.senlingspace.common.enums.*;
import com.senlingspace.common.utils.*;
import com.senlingspace.common.enums.LakalaPaymentTypeEnum;
import com.senlingspace.common.enums.LakalaTradeStateEnum;
import com.senlingspace.system.domain.*;
import com.senlingspace.system.domain.dto.*;
import com.senlingspace.system.domain.query.senling.QueryOrderExport;
import com.senlingspace.system.domain.vo.DetailsVo;
import com.senlingspace.system.domain.vo.InvestorCollectVo;
import com.senlingspace.system.domain.vo.InvestorShareVo;
import com.senlingspace.system.domain.vo.PosOrderQueryVo;
import com.senlingspace.system.domain.vo.PosOrderVoV2;
import com.senlingspace.system.domain.vo.*;
import com.senlingspace.system.mapper.*;
import com.senlingspace.system.service.ISlkjOrderService;
import com.senlingspace.system.service.ISlkjShopService;
import com.senlingspace.system.service.ISysMenuService;
import com.senlingspace.system.service.ISysUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.apache.commons.collections4.CollectionUtils;
import org.modelmapper.ModelMapper;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

import static com.senlingspace.common.utils.PageUtils.startPage;
import static com.senlingspace.common.utils.SecurityUtils.getDeptId;
import static com.senlingspace.common.utils.SecurityUtils.getLoginUser;

/**
 * 订单Service业务层处理
 *
 * @author SenlingSpace
 * @date 2024-07-01
 */
@Slf4j
@Service
public class SlkjOrderServiceImpl implements ISlkjOrderService {

    @Autowired
    private SlkjOrderMapper slkjOrderMapper;
    @Autowired
    private ProjectMapper projectMapper;
    @Autowired
    private ISysUserService userService;
    @Autowired
    private ISysMenuService menuService;
    @Autowired
    private SlkjOrderStatusLogMapper slkjOrderStatusLogMapper;
    @Autowired
    private SlkjShopMapper shopMapper;
    @Autowired
    private SlkjOrderPricingSnapshotMapper slkjOrderPricingSnapshotMapper;
    @Autowired
    private SlkjOrderSplitSnapshotMapper slkjOrderSplitSnapshotMapper;
    @Autowired
    private SlkjInvestorMapper slkjInvestorMapper;
    @Autowired
    private SlkjProductMapper slkjProductMapper;
    @Autowired
    private ISlkjShopService slkjShopService;
    @Autowired
    private SlkjOrderTrackingMapper slkjOrderTrackingMapper;
    @Autowired
    private SlkjCustomerMapper slkjCustomerMapper;
    @Autowired
    private SlkjTicketLevelMapper slkjTicketLevelMapper;
    @Autowired
    private SlkjShopProjectMapper slkjShopProjectMapper;
    @Autowired
    private SlkjCustomerAddressMapper slkjCustomerAddressMapper;


    @Override
    public Integer ticketUseNum(String orderNumber, Long shopId) {
        SlkjOrder slkjOrder = new SlkjOrder();
        slkjOrder.setOrderNumber(orderNumber);
//         判断订单是否为空
        List<SlkjOrder> slkjOrders = selectSlkjOrderList(slkjOrder);
        if (slkjOrders == null || slkjOrders.size() == 0) {
            throw new NoSuchElementException("未找到指定订单号");
        }

        // 判断订单是否属于指定门店
        for (int i = 0; i < slkjOrders.size(); i++) {
            SlkjOrder slkjOrder1 = slkjOrders.get(i);
            if (!slkjOrder1.getShopId().equals(shopId)) {
                throw new NoSuchElementException("不是本门店订单，无法核销");
            }

            if (!slkjOrder1.getPaymentStatus().equals(LakalaTradeStateEnum.SUCCESS.name())) {
                return 0;
            }
        }

        SlkjOrderTracking orderTracking = new SlkjOrderTracking();
        orderTracking.setOrderNumber(orderNumber);
        List<SlkjOrderTracking> slkjOrderTrackings = slkjOrderTrackingMapper.selectByConditions(orderTracking);
        if (slkjOrderTrackings == null || slkjOrderTrackings.size() != 1) {
            throw new NoSuchElementException("未查到指定订单数据：：" + orderNumber);
        }
        SlkjOrderTracking slkjOrderTracking = slkjOrderTrackings.get(0);
        Integer includedTicketQuantity = slkjOrderTracking.getIncludedTicketQuantity();
        Integer validatedTicketQuantity = slkjOrderTracking.getValidatedTicketQuantity();
        // 返回剩余核销票数
        return includedTicketQuantity - validatedTicketQuantity;
    }

    @SuppressWarnings("resource")
    @Override
    public PageInfo<MiniAppOrderVo> miniAppOrderList(String type, Long customerId, Long shopId, Integer pageNum, Integer pageSize) {
        log.info("微信小程序订单列表，参数：type = {}, customerId = {}, shopId = {}, pageNum = {}, pageSize = {}", type, customerId, shopId, pageNum, pageSize);
        Stopwatch stopwatch = Stopwatch.createStarted();
        Page<Object> page = PageUtils.simpleStartPage(pageNum, pageSize, true);
        List<SlkjOrder> orders = slkjOrderMapper.miniAppOrderList(type, customerId, shopId);
        log.info("微信小程序订单列表，查询结果：{}", JSON.toJSONString(orders));
        long total = page.getTotal();

        if (CollectionUtils.isEmpty(orders)) {
            return new PageInfo<>();
        }

        log.info("处理结果集...");
        List<Long> orderIds = orders.stream().map(SlkjOrder::getOrderId).collect(Collectors.toList());
        List<SlkjOrderPricingSnapshot> snapshots = slkjOrderPricingSnapshotMapper.selectByOrderIds(orderIds);

        Map<Long, List<SlkjOrderPricingSnapshot>> snapListMap = snapshots.stream().collect(Collectors.groupingBy(SlkjOrderPricingSnapshot::getOrderId));

        Map<Long, String> goodsMap = Maps.newHashMap();
        Map<Long, String> projectMap = Maps.newHashMap();
        if ("goods".equals(type)) {
            List<Long> goodsIds = snapshots.stream().map(SlkjOrderPricingSnapshot::getGoodsId).collect(Collectors.toList());
            goodsMap = slkjProductMapper.selectProductByProductIds(goodsIds).stream().collect(Collectors.toMap(SlkjProduct::getProductId, SlkjProduct::getProductImg));
        } else {
            List<Long> projectIds = orders.stream().map(SlkjOrder::getProjectId).collect(Collectors.toList());
            projectMap = projectMapper.selectProjectByIdList(projectIds).stream().collect(Collectors.toMap(Project::getProjectId, Project::getCover));
        }

        final List<MiniAppOrderVo> resultList = new ArrayList<>();
        MiniAppOrderVo vo;
        MiniAppOrderVo.Ticket ticket;
        MiniAppOrderVo.Goods goods;
        List<MiniAppOrderVo.Goods> goodsList;
        for (SlkjOrder order : orders) {
            vo = new MiniAppOrderVo();
            vo.setOrderId(order.getOrderId());
            vo.setOrderNumber(order.getOrderNumber());
            vo.setShopName(order.getShopName());
            vo.setSource(order.getSource());
            vo.setOrderType(order.getOrderType());

            vo.setBusinessStatus(order.getBusinessStatus());
            // 用户小程序中，只展示：待核销（UNREDEEMED）、已退款（REFUNDED）、已完成（COMPLETED）
            // 待核销（UNREDEEMED）、已核销（REDEEMED）、待支付（PENDING_PAYMENT）、订单取消（ORDER_CANCELLED）、已退款（REFUNDED）、已领手环（WRISTBAND_RECEIVED）、已领设备（DEVICE_RECEIVED）、已完成（COMPLETED）',
            List<OrderBusinessStatus> statuses = Arrays.asList(OrderBusinessStatus.REDEEMED, OrderBusinessStatus.WRISTBAND_RECEIVED, OrderBusinessStatus.DEVICE_RECEIVED, OrderBusinessStatus.COMPLETED);
            if (order.getOrderType() == OrderType.OT_101.getCode() && statuses.contains(OrderBusinessStatus.fromCode(order.getBusinessStatus()))) {
                vo.setBusinessStatus(OrderBusinessStatus.COMPLETED.getCode());
            }
            vo.setGoodsStatus(order.getGoodsStatus());
            vo.setTotalAmount(MoneyUtils.fen2Yuan(order.getActualAmount()));

            List<SlkjOrderPricingSnapshot> snaps = snapListMap.get(order.getOrderId());
            int sum = snaps.stream().mapToInt(SlkjOrderPricingSnapshot::getBayQuantity).sum();
            vo.setBuyCount(sum);

            vo.setTicket(null);
            vo.setGoods(null);
            if ("ticket".equals(type)) {
                ticket = new MiniAppOrderVo.Ticket();
                ticket.setCategoryName(snaps.get(0).getTicketCategoryName());
                ticket.setCover(projectMap.get(order.getProjectId()));
                ticket.setProjectName(order.getProjectName());
                vo.setTicket(ticket);
            } else {
                goodsList = new ArrayList<>();
                for (SlkjOrderPricingSnapshot snap : snaps) {
                    goods = new MiniAppOrderVo.Goods();
                    goods.setGoodsName(snap.getGoodsName());
                    String urls = goodsMap.get(snap.getGoodsId());
                    goods.setCover(urls);
                    // 如果商品图片是多张，只取第一张
                    if (StringUtils.isNotEmpty(urls) && urls.contains(",")) {
                        goods.setCover(urls.split(",")[0]);
                    }
                    goods.setBuyQuantity(snap.getBayQuantity());
                    goods.setPrice(MoneyUtils.fen2Yuan(snap.getUserActualAmount()));
                    goodsList.add(goods);
                    vo.setGoods(goodsList);
                }
            }
            resultList.add(vo);
        }

        log.info("处理结果集完成，耗时：{}", stopwatch.stop());
        PageInfo<MiniAppOrderVo> pageInfo = new PageInfo<>(resultList);
        pageInfo.setTotal(total);
        pageInfo.setPageNum(page.getPageNum());
        pageInfo.setPageSize(page.getPageSize());
        return pageInfo;
    }

    @Override
    public MiniAppOrderDetailVo miniAppOrderDetail(Long orderId) {
        log.info("微信小程序订单详情，参数：orderId = {}", orderId);
        SlkjOrder order = slkjOrderMapper.selectSlkjOrderByOrderId(orderId);
        if (order == null) {
            throw new NoSuchElementException("未查到指定订单数据：" + orderId);
        }

        MiniAppOrderDetailVo result = new MiniAppOrderDetailVo();
        result.setOrderId(orderId);
        result.setOrderNumber(order.getOrderNumber());
        result.setShopName(order.getShopName());
        result.setSource(order.getSource());
        result.setOrderType(order.getOrderType());
        result.setBusinessStatus(order.getBusinessStatus());
        // 用户小程序中，只展示：待核销（UNREDEEMED）、已退款（REFUNDED）、已完成（COMPLETED）
        // 待核销（UNREDEEMED）、已核销（REDEEMED）、待支付（PENDING_PAYMENT）、订单取消（ORDER_CANCELLED）、已退款（REFUNDED）、已领手环（WRISTBAND_RECEIVED）、已领设备（DEVICE_RECEIVED）、已完成（COMPLETED）',
        List<OrderBusinessStatus> statuses = Arrays.asList(OrderBusinessStatus.REDEEMED, OrderBusinessStatus.WRISTBAND_RECEIVED, OrderBusinessStatus.DEVICE_RECEIVED, OrderBusinessStatus.COMPLETED);
        if (order.getOrderType() == OrderType.OT_101.getCode() && statuses.contains(OrderBusinessStatus.fromCode(order.getBusinessStatus()))) {
            result.setBusinessStatus(OrderBusinessStatus.COMPLETED.getCode());
        }
        result.setGoodsStatus(order.getGoodsStatus());

        result.setVerifyCode("");
        // 只有支付成功的订单才显示核销码
        if (order.getPaymentStatus().equals(LakalaTradeStateEnum.SUCCESS.name())) {
            String qrcode = AesUtil.encryptQrcode(order.getShopId() + "#" + order.getVerifyCode() + "#" + order.getOrderId());
            result.setVerifyCode(qrcode);
        }

        // 邮寄订单不显示核销码
        if (order.getOrderType() == OrderType.OT_102.getCode() && StringUtils.isNotBlank(order.getAddressSnapshot())) {
            result.setVerifyCode("");
        }

        result.setTotalAmount(MoneyUtils.fen2Yuan(order.getTotalAmount()));
        result.setCreateTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, order.getCreateTime()));

        result.setPaymentTime("");
        if (order.getPaymentTime() != null) {
            result.setPaymentTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, order.getPaymentTime()));
        }

        SlkjShop shop = slkjShopService.selectSlkjShopByShopId(order.getShopId());
        String address = shop.getCountyName().replaceAll("/", "");
        result.setShopAddress(address + shop.getAddress());

        SlkjCustomer customer = slkjCustomerMapper.getCustomerByCustomerId(order.getCustomerId());
        result.setBuyPhone(customer != null ? customer.getPhone() : "");

        result.setTicket(null);
        result.setGoods(null);
        List<SlkjOrderPricingSnapshot> snapshots = slkjOrderPricingSnapshotMapper.selectByOrderId(orderId);
        if (order.getOrderType() == OrderType.OT_101.getCode()) {
            MiniAppOrderDetailVo.Ticket ticket = new MiniAppOrderDetailVo.Ticket();
            Project project = projectMapper.selectProjectByProjectId(order.getProjectId());
            ticket.setCover(project.getCover());
            ticket.setProjectName(order.getProjectName());
            SlkjOrderPricingSnapshot snapshot = snapshots.get(0);
            ticket.setCategoryName(snapshot.getTicketCategoryName());
            ticket.setBuyCount(snapshot.getBayQuantity());

            SlkjTicketLevel ticketLevel = slkjTicketLevelMapper.selectSlkjTicketLevelById(snapshot.getTicketLevelId());
            ticket.setRemark(ticketLevel.getRemark());

            SlkjShopProject shopProject = new SlkjShopProject();
            shopProject.setShopId(order.getShopId());
            shopProject.setProjectId(order.getProjectId());
            shopProject.setDelFlag((byte) 0);
            SlkjShopProject sp = slkjShopProjectMapper.selectSlkjShopProjectList(shopProject).get(0);
            LocalDate startDate = sp.getStartDate();
            LocalDate endDate = sp.getEndDate();
            ticket.setCycleTimes(Lists.newArrayList());
            if (Objects.nonNull(startDate) && Objects.nonNull(endDate)) {
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                ticket.setCycleTimes(Lists.newArrayList(startDate.format(formatter), endDate.format(formatter)));
            }
            result.setTicket(ticket);
        } else if (order.getOrderType() == OrderType.OT_102.getCode()) {
            List<Long> goodsIds = snapshots.stream().map(SlkjOrderPricingSnapshot::getGoodsId).collect(Collectors.toList());
            Map<Long, String> goodsCoverMap = slkjProductMapper.selectProductByProductIds(goodsIds).stream().collect(Collectors.toMap(SlkjProduct::getProductId, SlkjProduct::getProductImg));
            MiniAppOrderDetailVo.Goods goods = new MiniAppOrderDetailVo.Goods();
            List<MiniAppOrderDetailVo.Item> items = Lists.newArrayList();
            snapshots.forEach(snap -> {
                MiniAppOrderDetailVo.Item item = new MiniAppOrderDetailVo.Item();
                String urls = goodsCoverMap.get(snap.getGoodsId());
                item.setCover(urls);
                if (StringUtils.isNotBlank(urls) && urls.contains(",")) {
                    item.setCover(urls.split(",")[0]);
                }
                item.setGoodsName(snap.getGoodsName());
                item.setBuyCount(snap.getBayQuantity());
                item.setPrice(MoneyUtils.fen2Yuan(snap.getUserActualAmount()));
                item.setAttribute(snap.getAttribute());
                items.add(item);
            });
            goods.setItems(items);

            String json = order.getAddressSnapshot();
            if (StringUtils.isNotBlank(json)) {
                CustomerAddressDTO customerAddress = JSON.parseObject(json, CustomerAddressDTO.class);
                goods.setReceiverAddress(customerAddress.getDetailAddress());
                goods.setReceiverName(customerAddress.getReceiverName());
                goods.setReceiverPhone(customerAddress.getReceiverPhone());
            }
            result.setGoods(goods);
        }

        // 核销时间
        List<SlkjOrderStatusLog> logs = slkjOrderStatusLogMapper.findByOrderId(orderId);
        if (CollectionUtils.isNotEmpty(logs)) {
            logs.stream()
                    .filter(log -> log.getStatus().equals(OrderBusinessStatus.REDEEMED.getCode()))
                    .findFirst()
                    .ifPresent(log -> result.setVerifyTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, log.getChangeTime())));
        }

        log.info("微信小程序订单详情，结果：{}", JSON.toJSONString(result));
        return result;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public AjaxResult validateQrcode(String qrcode) {
        if (StringUtils.isBlank(qrcode)) {
            log.info("二维码为空！");
            return AjaxResult.error("二维码有误！");
        }

        // 格式为：shop_id#verify_code#order_id
        String content = AesUtil.decryptQrcode(qrcode);
        if (StringUtils.isBlank(content) || !content.contains("#") || content.split("#").length != 3) {
            log.info("二维码格式有误，假冒二维码！");
            return AjaxResult.error("二维码有误！");
        }

        String[] params = content.split("#");
        Long shopId = Long.parseLong(params[0]);
        String verifyCode = params[1];
        Long orderId = Long.parseLong(params[2]);
        SlkjOrder order = slkjOrderMapper.selectSlkjOrderByOrderId(orderId);
        if (order == null) {
            return AjaxResult.error("订单不存在！");
        }

        if (!verifyCode.equals(order.getVerifyCode())) {
            log.info("核销码与订单号不匹配！");
            return AjaxResult.error("核销码有误！");
        }

        if (!shopId.equals(order.getShopId())) {
            log.info("门店与订单不匹配！");
            return AjaxResult.error("禁止跨店核销！");
        }

        if (!order.getPaymentStatus().equals(LakalaTradeStateEnum.SUCCESS.name())) {
            return AjaxResult.error("订单未支付，禁止核销！");
        }

        order.setUpdateBy(SecurityUtils.getUserId() + "");
        order.setUpdateTime(DateUtils.getNowDate());

        List<SlkjOrderStatusLog> statusLogs = new ArrayList<>();
        SlkjOrderStatusLog orderStatusLog;
        OrderType orderType = OrderType.fromCode(order.getOrderType());
        switch (orderType) {
            case OT_101:
                if (!order.getBusinessStatus().equals(OrderBusinessStatus.UNREDEEMED.getCode())) {
                    return AjaxResult.error("禁止重复核销！");
                }
                orderStatusLog = new SlkjOrderStatusLog();
                orderStatusLog.setOrderId(order.getOrderId());
                orderStatusLog.setStatus(OrderBusinessStatus.REDEEMED.getCode());
                orderStatusLog.setChangeBy(SecurityUtils.getUserId());
                orderStatusLog.setChangeTime(DateUtils.getNowDate());
                statusLogs.add(orderStatusLog);
                order.setBusinessStatus(OrderBusinessStatus.REDEEMED.getCode());
                break;
            case OT_102:
                if (!order.getGoodsStatus().equals(GoodsStatusEnum.WAITING_FOR_PICKUP.name())) {
                    return AjaxResult.error("禁止重复核销！");
                }
                // 已核销
                orderStatusLog = new SlkjOrderStatusLog();
                orderStatusLog.setOrderId(order.getOrderId());
                orderStatusLog.setStatus(OrderBusinessStatus.REDEEMED.getCode());
                orderStatusLog.setChangeBy(SecurityUtils.getUserId());
                orderStatusLog.setChangeTime(order.getUpdateTime());
                statusLogs.add(orderStatusLog);

                ThreadUtil.sleep(50);
                // 已完成
                orderStatusLog = new SlkjOrderStatusLog();
                orderStatusLog.setOrderId(order.getOrderId());
                orderStatusLog.setStatus(OrderBusinessStatus.COMPLETED.getCode());
                orderStatusLog.setChangeBy(SecurityUtils.getUserId());
                orderStatusLog.setChangeTime(DateUtils.getNowDate());
                statusLogs.add(orderStatusLog);
                order.setGoodsStatus(GoodsStatusEnum.COMPLETED.name());
                break;
            default:
                return AjaxResult.error("订单有误，请咨询客服！");
        }
        log.info("更新订单状态：{}", JSON.toJSONString(order));
        slkjOrderMapper.updateSlkjOrder(order);

        log.info("批量插入订单状态日志：{}", JSON.toJSONString(statusLogs));
        slkjOrderStatusLogMapper.batchInsert(statusLogs);

        log.info("订单 [order_id={}] 核销成功！", order.getOrderId());
        return AjaxResult.success("核销成功！", order.getOrderId());
    }

    @Override
    public AjaxResult updateAddress(OrderAddressVo req, Long customerId, Long shopId) {
        if (req == null || customerId == null || shopId == null) {
            return AjaxResult.error("参数错误！");
        }

        if (req.getType() == 102 && req.getAddressId() == null) {
            return AjaxResult.error("地址ID不能为空！");
        }

        SlkjOrder order = slkjOrderMapper.selectSlkjOrderByOrderId(req.getOrderId());
        if (order == null) {
            return AjaxResult.error("订单不存在！");
        }

        if (!order.getCustomerId().equals(customerId)) {
            return AjaxResult.error("非法操作！");
        }

        if (!order.getShopId().equals(shopId)) {
            return AjaxResult.error("非法操作！");
        }

        String json = null;
        if (req.getType() == 102) {
            SlkjCustomerAddress address = slkjCustomerAddressMapper.selectById(req.getAddressId());
            json = JSON.toJSONString(address);
        }

        int count = slkjOrderMapper.updateOrderAddress(order.getOrderId(), json);

        return count == 1 ? AjaxResult.success("修改成功！", order.getOrderId()) : AjaxResult.error("修改失败！");
    }

    @Override
    public PageInfo<VerificationRecordsVo> verificationRecords(VerificationRecordsRequest verificationRecordsRequest) {
        Page<Object> page = PageUtils.startPageExt(true);
        List<VerificationRecordsDto> recordsDtos = slkjOrderMapper.verificationRecords(verificationRecordsRequest);
        long total = page.getTotal();

        if (CollectionUtils.isEmpty(recordsDtos)) {
            return new PageInfo<>();
        }

        List<Long> orderIds = recordsDtos.stream().map(VerificationRecordsDto::getOrderId).collect(Collectors.toList());
        List<SlkjOrderPricingSnapshot> pricingSnapshots = slkjOrderPricingSnapshotMapper.selectByOrderIds(orderIds);
        Map<Long, List<SlkjOrderPricingSnapshot>> listMap = pricingSnapshots.stream()
                .collect(Collectors.groupingBy(SlkjOrderPricingSnapshot::getOrderId));

        final List<VerificationRecordsVo> records = new ArrayList<>();
        for (VerificationRecordsDto dto : recordsDtos) {
            VerificationRecordsVo vo = new VerificationRecordsVo();
            vo.setOrderNumber(dto.getOrderNumber());
            vo.setVerifyCode(dto.getVerifyCode());
            vo.setVerifyTime(dto.getVerifyTime());
            vo.setCreateTime(dto.getCreateTime());
            vo.setVerifyStatus(dto.getVerifyStatus());
            vo.setVerifyUser(dto.getVerifyUser());
            vo.setSource(dto.getSource());
            vo.setOrderAmount(MoneyUtils.fen2Yuan(dto.getTotalAmount()));
            vo.setFailCause(dto.getFailCause());
            vo.setCustomerPhone(dto.getCustomerPhone());

            List<VerificationRecordsVo.Goods> goodsList = new ArrayList<>();
            if (listMap.containsKey(dto.getOrderId())) {
                List<SlkjOrderPricingSnapshot> snapshots = listMap.get(dto.getOrderId());
                for (SlkjOrderPricingSnapshot snapshot : snapshots) {
                    VerificationRecordsVo.Goods goods = new VerificationRecordsVo.Goods();
                    boolean flag = "GOODS".equals(snapshot.getItemType());
                    goods.setGoodsName(flag ? snapshot.getGoodsName() : dto.getProjectName() + "（" + snapshot.getTicketLevelName() + "）");
                    if (flag) {
                        SlkjProduct product = slkjProductMapper.selectSlkjProductByProductId(snapshot.getGoodsId());
                        goods.setGoodsUrl(product.getProductImg());
                    } else {
                        Project project = projectMapper.selectProjectByProjectId(dto.getProjectId());
                        goods.setGoodsUrl(project.getCover());
                    }
                    goods.setGoodsType(snapshot.getItemType());
                    goods.setBuyQuantity(snapshot.getBayQuantity());
                    goods.setQuantity(snapshot.getQuantity());
                    goodsList.add(goods);
                }
            }
            vo.setGoodsList(goodsList);
            records.add(vo);
        }

        PageInfo<VerificationRecordsVo> pageInfo = new PageInfo<>(records);
        pageInfo.setTotal(total);
        pageInfo.setPageNum(page.getPageNum());
        pageInfo.setPageSize(page.getPageSize());
        return pageInfo;
    }

    @SuppressWarnings("resource")
    @Override
    public PageInfo<PaymentUponReceiptDTO> paymentUponReceipt(PaymentUponReceiptRequest request, boolean paginate) {
        //     SYSTEM("00","系统用户"),
        //     OPERATE("02","运营方"),
        //     SHOP("03","门店"),
        //     INVESTOR("04","投资人"),
        //     COPYRIGHT("05","版权方");
        if (SecurityUtils.getHeadquarters().equals(UserType.SHOP.getCode())) {
            request.setShopId(shopMapper.selectSlkjShopByDeptId(getDeptId()).getShopId());
        }

        log.info("查询到付商品订单列表，参数：{}", JSON.toJSONString(request));
        Page<Object> page = PageUtils.startPageExt(paginate);
        List<PaymentUponReceiptDTO> purs = slkjOrderMapper.paymentUponReceipt(request);
        long total = page.getTotal();

        if (CollectionUtils.isEmpty(purs)) {
            return new PageInfo<>();
        }

        List<Long> orderIds = purs.stream().map(PaymentUponReceiptDTO::getOrderId).collect(Collectors.toList());
        Map<Long, Integer> buyQuantityMap = slkjOrderPricingSnapshotMapper.selectByOrderIds(orderIds)
                .stream()
                .collect(Collectors.groupingBy(SlkjOrderPricingSnapshot::getOrderId, Collectors.summingInt(SlkjOrderPricingSnapshot::getBayQuantity)));
        for (PaymentUponReceiptDTO pur : purs) {
            pur.setBuyQuantity(buyQuantityMap.get(pur.getOrderId()));
            pur.setTotalAmount(MoneyUtils.fen2Yuan(Long.parseLong(pur.getTotalAmount())));
        }

        PageInfo<PaymentUponReceiptDTO> pageInfo = new PageInfo<>(purs);
        pageInfo.setTotal(total);
        pageInfo.setPageNum(page.getPageNum());
        pageInfo.setPageSize(page.getPageSize());
        return pageInfo;
    }

    @Override
    public AjaxResult paymentUponReceiptDetail(Long orderId) {
        SlkjOrder order = slkjOrderMapper.selectSlkjOrderByOrderId(orderId);
        if (Objects.isNull(order)) {
            return AjaxResult.warn("订单不存在！");
        }

        PaymentUponReceiptDetailVO result = new PaymentUponReceiptDetailVO();
        result.setOrderId(order.getOrderId());
        result.setShopName(order.getShopName());
        result.setSource(order.getSource());
        result.setOrderNumber(order.getOrderNumber());
        result.setCustomerPhone(order.getCreateBy());
        result.setOrderStatus(order.getGoodsStatus());
        result.setCreateTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, order.getCreateTime()));

        Date paymentTime = order.getPaymentTime();
        if (Objects.nonNull(paymentTime)) {
            result.setPaymentTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, paymentTime));
        }

        result.setTotalAmount(MoneyUtils.fen2Yuan(order.getActualAmount()));
        result.setExpressNumber(order.getExpressNumber());
        result.setPaymentType(order.getPaymentType());

        // 收获地址信息
        String json = order.getAddressSnapshot();
        result.setReceiverAddress("");
        result.setReceiverName("");
        result.setReceiverPhone("");
        if (StringUtils.isNotBlank(json)) {
            SlkjCustomerAddress customerAddress = JSON.parseObject(json, SlkjCustomerAddress.class);
            result.setReceiverAddress(customerAddress.getDetailAddress());
            result.setReceiverName(customerAddress.getReceiverName());
            result.setReceiverPhone(customerAddress.getReceiverPhone());
        }

        List<PaymentUponReceiptDetailVO.Goods> goodsList = new ArrayList<>();
        slkjOrderPricingSnapshotMapper.selectGoodsByOrderIds(Collections.singletonList(orderId))
                .forEach(snapshot -> {
                    PaymentUponReceiptDetailVO.Goods goods = new PaymentUponReceiptDetailVO.Goods();
                    goods.setGoodsType(snapshot.getItemType());
                    if ("GOODS".equals(snapshot.getItemType())) {
                        goods.setGoodsName(snapshot.getGoodsName());
                    } else {
                        goods.setGoodsName(order.getProjectName() + "（" + snapshot.getTicketCategoryName() + "）");
                    }
                    goods.setBuyQuantity(snapshot.getBayQuantity());
                    goods.setUserActualAmount(MoneyUtils.fen2Yuan(snapshot.getUserActualAmount()));
                    goodsList.add(goods);
                });
        result.setGoodsList(goodsList);

        return AjaxResult.success(result);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public AjaxResult updateOrderDeliveryStatus(OrderDeliveryStatusRequest request) {
        if (Objects.isNull(request.getOrderId())) {
            return AjaxResult.error("订单ID不能为空！");
        }

        String deliveryStatus = request.getDeliveryStatus();
        String expressNumber = request.getExpressNumber();

        if (StringUtils.isBlank(deliveryStatus)) {
            return AjaxResult.error("发货状态不能为空！");
        }

        if (StringUtils.isBlank(expressNumber) && GoodsStatusEnum.SHIPPED.name().equals(deliveryStatus)) {
            return AjaxResult.error("请填写快递单号！");
        }

        SlkjOrder order = slkjOrderMapper.selectSlkjOrderByOrderId(request.getOrderId());
        if (Objects.isNull(order)) {
            return AjaxResult.error("订单不存在！");
        }

        if (StringUtils.isBlank(order.getAddressSnapshot())) {
            return AjaxResult.error("订单收货地址为空，无法发货！");
        }

        String goodsStatus = order.getGoodsStatus();
        if (goodsStatus.equals(GoodsStatusEnum.COMPLETED.name())) {
            return AjaxResult.error("订单已完成，无法发货！");
        }

        String paymentStatus = order.getPaymentStatus();
        if (paymentStatus.equals(LakalaTradeStateEnum.REFUND.name())) {
            return AjaxResult.error("订单已退款！");
        }

        if (!paymentStatus.equals(LakalaTradeStateEnum.SUCCESS.name())) {
            return AjaxResult.error("订单未支付！");
        }

        order.setGoodsStatus(deliveryStatus);
        if (GoodsStatusEnum.SHIPPED.name().equals(deliveryStatus)) {
            order.setExpressNumber(expressNumber);
        }
        order.setUpdateBy(SecurityUtils.getUserId() + "");
        order.setUpdateTime(DateUtils.getNowDate());

        log.info("更新订单发货状态：{}", JSON.toJSONString(order));
        slkjOrderMapper.updateSlkjOrder(order);

        SlkjOrderStatusLog orderStatusLog = new SlkjOrderStatusLog();
        orderStatusLog.setOrderId(order.getOrderId());
        orderStatusLog.setStatus(deliveryStatus);
        orderStatusLog.setChangeBy(SecurityUtils.getUserId());
        orderStatusLog.setChangeTime(DateUtils.getNowDate());
        log.info("更新订单发货状态日志：{}", JSON.toJSONString(orderStatusLog));
        slkjOrderStatusLogMapper.insert(orderStatusLog);

        return AjaxResult.success("success");
    }

    @Override
    public List<OrderListExportVo> selectOrderListExportList(QueryOrderExport queryOrderExport) {
        List<OrderListExportVo> listExportVos = new ArrayList<>();
        List<OrderDetailVo> orderDetailVos = new ArrayList<>();
        OrderDto slkjOrder = new OrderDto();
        slkjOrder.setShopId(queryOrderExport.getShopId());
        slkjOrder.setOrderNumber(queryOrderExport.getOrderNumber());
        slkjOrder.setBeginTime(queryOrderExport.getBeginTime());
        slkjOrder.setEndTime(queryOrderExport.getEndTime());
        slkjOrder.setSource(queryOrderExport.getSource());
        slkjOrder.setProjectName(queryOrderExport.getProjectName());
        slkjOrder.setBusinessStatus(queryOrderExport.getBusinessStatus());
        slkjOrder.setOrderNumber(queryOrderExport.getOrderNumber());
        // 权限限制
        if (UserType.SHOP.getCode().equals(SecurityUtils.getHeadquarters())) {
            log.info("门店账号查看订单");
            SlkjShop shopList = shopMapper.selectSlkjShopByDeptId(getDeptId());
            slkjOrder.setShopId(shopList.getShopId());
        } else if (UserType.OPERATE.getCode().equals(SecurityUtils.getHeadquarters()) || UserType.SYSTEM.getCode().equals(SecurityUtils.getHeadquarters())) {
            log.info("运营方查看订单");
        }

        List<OrderDto> orderDtos = slkjOrderMapper.listDetail(slkjOrder);
        for (OrderDto orderDto : orderDtos) {
            OrderListExportVo orderListExportVo = new OrderListExportVo();

            List<SlkjOrderPricingSnapshot> ticketLevelCategory = orderDto.getTicketLevelCategory();
            Integer bayQuantitySum = 0;
            Integer bayQuantityGoodsSum = 0;
            String ticketLevelName = "";
            String ticketCategoryName = "";
            String goodsName = "";
//            计算商品总数
            for (SlkjOrderPricingSnapshot slkjOrderPricingSnapshot : ticketLevelCategory) {

                if (orderDto.getOrderType() == OrderType.OT_101.getCode() && slkjOrderPricingSnapshot.getBayQuantity() != null) {
                    //票类订单
                    slkjOrderPricingSnapshot.setTicketCategoryName(slkjOrderPricingSnapshot.getTicketCategoryName() + "*" + slkjOrderPricingSnapshot.getBayQuantity());
                    // slkjOrderPricingSnapshot.setTicketCategoryName(slkjOrderPricingSnapshot.getTicketCategoryName());
                    bayQuantitySum += slkjOrderPricingSnapshot.getBayQuantity();
                    orderDto.setBayQuantitySum(bayQuantitySum);
                    ticketLevelName = StringUtils.join(ticketLevelName, slkjOrderPricingSnapshot.getTicketLevelName() + "/");
                    ticketCategoryName = StringUtils.join(ticketCategoryName, slkjOrderPricingSnapshot.getTicketCategoryName() + "/");
                } else if (orderDto.getOrderType() == OrderType.OT_102.getCode() && slkjOrderPricingSnapshot.getBayQuantity() != null) {
                    //商品类订单
                    slkjOrderPricingSnapshot.setGoodsName(slkjOrderPricingSnapshot.getGoodsName() + "*" + slkjOrderPricingSnapshot.getBayQuantity());
                    // slkjOrderPricingSnapshot.setGoodsName(slkjOrderPricingSnapshot.getGoodsName());
                    bayQuantityGoodsSum += slkjOrderPricingSnapshot.getBayQuantity();
                    orderDto.setBayQuantityGoodsSum(bayQuantityGoodsSum);
                    goodsName = StringUtils.join(goodsName, slkjOrderPricingSnapshot.getGoodsName() + "/");


                } else if (orderDto.getOrderType() == OrderType.OT_103.getCode() && slkjOrderPricingSnapshot.getBayQuantity() != null) {
                    //混合订单
                    if (slkjOrderPricingSnapshot.getItemType().equals("TICKET")) {
                        //混合订单中的票类订单
                        slkjOrderPricingSnapshot.setTicketCategoryName(slkjOrderPricingSnapshot.getTicketCategoryName() + "*" + slkjOrderPricingSnapshot.getBayQuantity());
                        // slkjOrderPricingSnapshot.setTicketCategoryName(slkjOrderPricingSnapshot.getTicketCategoryName());
                        bayQuantitySum += slkjOrderPricingSnapshot.getBayQuantity();
                        orderDto.setBayQuantitySum(bayQuantitySum);
                        ticketLevelName = StringUtils.join(ticketLevelName, slkjOrderPricingSnapshot.getTicketLevelName() + "/");
                        ticketCategoryName = StringUtils.join(ticketCategoryName, slkjOrderPricingSnapshot.getTicketCategoryName() + "/");

                    } else {
                        //混合订单中的商品订单
                        slkjOrderPricingSnapshot.setGoodsName(slkjOrderPricingSnapshot.getGoodsName() + "*" + slkjOrderPricingSnapshot.getBayQuantity());
                        // slkjOrderPricingSnapshot.setGoodsName(slkjOrderPricingSnapshot.getGoodsName());
                        bayQuantityGoodsSum += slkjOrderPricingSnapshot.getBayQuantity();
                        orderDto.setBayQuantityGoodsSum(bayQuantityGoodsSum);
                        goodsName = StringUtils.join(goodsName, slkjOrderPricingSnapshot.getGoodsName() + "/");
                    }


                }


            }

            List<SlkjOrderSplitSnapshotDto> slkjOrderSplitSnapshot = orderDto.getSlkjOrderSplitSnapshot();
//          如果是投资人名称 去除赋值到字段中
            for (SlkjOrderSplitSnapshotDto orderSplitSnapshot : slkjOrderSplitSnapshot) {

                if (SlkjOrderSplitSnapshotDto.INVESTOR.equals(orderSplitSnapshot.getRelatedType())) {
                    String otherFields = orderSplitSnapshot.getOtherFields();
                    JSONObject jsonObject = JSON.parseObject(otherFields);
                    Object investorName = jsonObject.get("investorName");
                    orderSplitSnapshot.setInvestorName(investorName.toString());
                }
            }


            // 使用 BeanUtils 进行深拷贝 金额转化为元给前端
            ModelMapper modelMapper = new ModelMapper();
            OrderDetailVo orderDetailVo = modelMapper.map(orderDto, OrderDetailVo.class);
            orderDetailVos.add(orderDetailVo);
            orderListExportVo.setOrderNumber(orderDto.getOrderNumber());
            orderListExportVo.setCreateTime(orderDto.getCreateTime());
            orderListExportVo.setShopName(orderDto.getShopName());
            orderListExportVo.setSource(orderDto.getSource());
            orderListExportVo.setProjectName(orderDto.getProjectName());
            orderListExportVo.setTicketLevelName(ticketLevelName);
            orderListExportVo.setTicketCategoryName(ticketCategoryName);
            orderListExportVo.setBayQuantitySum(bayQuantitySum);
            orderListExportVo.setGoodsName(goodsName);
            orderListExportVo.setBayQuantityGoodsSum(bayQuantityGoodsSum);
            orderListExportVo.setVerifyCode(orderDto.getVerifyCode());
            orderListExportVo.setTotalAmount(orderDetailVo.getTotalAmount());
            orderListExportVo.setActualAmount(orderDetailVo.getActualAmount());
            orderListExportVo.setPaymentType(orderDto.getPaymentType());
            if (orderDto.getOrderType() == OrderType.OT_101.getCode()) {
                orderListExportVo.setBusinessStatus(orderDto.getBusinessStatus());
            }else {
                orderListExportVo.setBusinessStatus(orderDto.getGoodsStatus());
            }


            orderListExportVo.setPaymentStatus(orderDto.getPaymentStatus());
            listExportVos.add(orderListExportVo);
        }

        return listExportVos;
    }

    @Override
    public Boolean getStatusByOrderNumber(String orderNumber) {

        return slkjOrderMapper.getStatusByOrderNumber(orderNumber);
    }

    @Override
    public ReceiptInfoVo getReceiptInfo(Long orderId) {
        log.info("获取订单 [order_id={}] 小票信息！", orderId);
        ReceiptInfoVo result = new ReceiptInfoVo();
        SlkjOrder order = slkjOrderMapper.selectSlkjOrderByOrderId(orderId);
        result.setShopName(order.getShopName());
        result.setOrderNumber(order.getOrderNumber());
        result.setOrderId(order.getOrderId());
        result.setProjectName(order.getProjectName());
        result.setCreateTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, order.getCreateTime()));
        result.setTotalPrice(MoneyUtils.fen2Yuan(order.getActualAmount()));

        result.setCashier("0" + order.getCreateBy());
        OrderSource orderSource = OrderSource.fromCode(order.getSource());
        if (!orderSource.equals(OrderSource.SHOP)) {
            result.setCashier(orderSource.getDescription());
        }

        SlkjShop shop = shopMapper.selectSlkjShopByShopId(order.getShopId());
        result.setShopMobile(shop.getContactTel());
        result.setShopAddress(shop.getAddress());
        result.setServiceMobile(SenlingSpaceConfig.getServiceMobile());

        List<ReceiptInfoVo.Goods> goodsList = new ArrayList<>();
        List<SlkjOrderPricingSnapshot> pricingSnapshots = slkjOrderPricingSnapshotMapper.selectByOrderId(orderId);
        ReceiptInfoVo.Goods goods;
        for (SlkjOrderPricingSnapshot pricingSnapshot : pricingSnapshots) {
            goods = new ReceiptInfoVo.Goods();
            String name;
            if ("TICKET".equals(pricingSnapshot.getItemType())) {
                name = pricingSnapshot.getTicketCategoryName();
            } else {
                name = pricingSnapshot.getGoodsName();

                // 小票显示商品规格
                String attribute = pricingSnapshot.getAttribute();
                if (StringUtils.isNotBlank(attribute) && !"无".equals(attribute)) {
                    name = pricingSnapshot.getGoodsName() + " * " + attribute;
                }
            }
            goods.setContent(name + " * " + pricingSnapshot.getBayQuantity());
            goods.setGoodsTotalPrice(MoneyUtils.fen2Yuan(pricingSnapshot.getUserActualAmount()));
            goodsList.add(goods);
        }
        log.info("goodsList：{}", JSON.toJSONString(goodsList));
        result.setGoodsList(goodsList);

        log.info("订单 [order_id={}] 小票信息：{}", orderId, JSON.toJSONString(result));
        return result;
    }

    public InvestorPersionVO getInvestorTotalAmount(InvestorCollectVo investorCollectVo) {
        LoginUser loginUser = getLoginUser();
        SysUser user = loginUser.getUser();
//        if ( user.getUserType().equals("04")){
        SlkjInvestor slkjInvestor = new SlkjInvestor();
        slkjInvestor.setPhoneNumber(user.getUserName());
        // 获取投资人id
        List<SlkjInvestor> slkjInvestors = slkjInvestorMapper.selectSlkjInvestorList(slkjInvestor);

        if (slkjInvestors != null) {
            SlkjInvestor slkjInvestor1 = slkjInvestors.get(0);
            Long investorId = slkjInvestor1.getInvestorId();
            InvestorPersionVO investorTotalAmount = slkjOrderMapper.getInvestorTotalAmount(investorId);

            investorCollectVo.setInvestorId(investorId);
            List<InvestorShareDTO> investorOrdersByDate = slkjOrderMapper.getInvestorOrdersByDate(investorCollectVo);
            investorTotalAmount.setInvestorShareDTOS((ArrayList<InvestorShareDTO>) investorOrdersByDate);
            return investorTotalAmount;
        }

        return new InvestorPersionVO();
    }


    /**
     * 投资方日分账汇总
     *
     * @param investorShareVo 订单
     * @return 订单集合
     */
    public List<InvestorCollectDTO> getInvestorCollect(InvestorCollectVo investorShareVo) {
// todo 门店账号只能查询到自己门店的数据
        return slkjOrderMapper.getInvestorCollect(investorShareVo);
    }

    /**
     * 投资方日分账明细表
     *
     * @param investorShareVo 订单
     * @return 订单集合
     */
    public List<InvestorShareDTO> getInvestorProfitShare(InvestorShareVo investorShareVo) {
// todo 门店账号只能查询到自己门店的数据
        return slkjOrderMapper.getInvestorProfitShare(investorShareVo);
    }

    /**
     * 查询有退款权限的账户
     *
     * @param shopId 门店id
     * @return 订单
     */
    @Override
    public List<SysUser> listPre(Long shopId) {

        // 先去查一下门店对应的部门id
        SlkjShop slkjShop = slkjShopService.selectSlkjShopByShopId(shopId);
        Long deptId = slkjShop.getDeptId();
        SysUser user = new SysUser();
        // 添加条件只有门店角色
        String code = UserType.SHOP.getCode();
        user.setUserType(code);
        user.setDeptId(deptId);
        List<SysUser> list = userService.selectUserNoPreList(user);

        for (Iterator<SysUser> iterator = list.iterator(); iterator.hasNext(); ) {
            SysUser sysUser = iterator.next();
            Set<String> perms = menuService.selectMenuPermsByUserId(sysUser.getUserId());
//         todo 后期修改为和其它权限字符一致的字符，查看怎么动态获取不写死   退款权限的权限标识
            if (!perms.contains("checkRole")) {
                iterator.remove();
            }
        }
        return list;
    }


    /**
     * 查询订单
     *
     * @param orderId 订单主键
     * @return 订单
     */
    @Override
    public SlkjOrder selectSlkjOrderByOrderId(Long orderId) {
        return slkjOrderMapper.selectSlkjOrderByOrderId(orderId);
    }

    /**
     * 查询订单列表和详情
     *
     * @param slkjOrder 订单
     * @return 订单
     */
    @Override
    public PageInfo<OrderDetailVo> listDetail(OrderDto slkjOrder) {
        List<OrderDetailVo> orderDetailVos = new ArrayList<>();

        // 权限限制
        if (UserType.SHOP.getCode().equals(SecurityUtils.getHeadquarters())) {
            log.info("门店账号查看订单");
            SlkjShop shopList = shopMapper.selectSlkjShopByDeptId(getDeptId());
            slkjOrder.setShopId(shopList.getShopId());
        } else if (UserType.OPERATE.getCode().equals(SecurityUtils.getHeadquarters()) || UserType.SYSTEM.getCode().equals(SecurityUtils.getHeadquarters())) {
            log.info("运营方查看订单");
        }

        startPage();
        List<OrderDto> orderDtos = slkjOrderMapper.listDetail(slkjOrder);
        if (CollectionUtils.isEmpty(orderDtos)) {
            return new PageInfo<>(Lists.newArrayList());
        }

        for (OrderDto orderDto : orderDtos) {

            List<SlkjOrderPricingSnapshot> ticketLevelCategory = orderDto.getTicketLevelCategory();
            Integer bayQuantitySum = 0;
            Integer bayQuantityGoodsSum = 0;
//            计算商品总数
            for (SlkjOrderPricingSnapshot slkjOrderPricingSnapshot : ticketLevelCategory) {


                if (orderDto.getOrderType() == OrderType.OT_101.getCode() && slkjOrderPricingSnapshot.getBayQuantity() != null) {
                    //票类订单
                    // slkjOrderPricingSnapshot.setTicketCategoryName(slkjOrderPricingSnapshot.getTicketCategoryName() + "*" + slkjOrderPricingSnapshot.getBayQuantity());
                    slkjOrderPricingSnapshot.setTicketCategoryName(slkjOrderPricingSnapshot.getTicketCategoryName());
                    bayQuantitySum += slkjOrderPricingSnapshot.getBayQuantity();
                    orderDto.setBayQuantitySum(bayQuantitySum);

                } else if (orderDto.getOrderType() == OrderType.OT_102.getCode() && slkjOrderPricingSnapshot.getBayQuantity() != null) {
                    //商品类订单
                    // slkjOrderPricingSnapshot.setGoodsName(slkjOrderPricingSnapshot.getGoodsName() + "*" + slkjOrderPricingSnapshot.getBayQuantity());
                    slkjOrderPricingSnapshot.setGoodsName(slkjOrderPricingSnapshot.getGoodsName());
                    bayQuantityGoodsSum += slkjOrderPricingSnapshot.getBayQuantity();
                    orderDto.setBayQuantityGoodsSum(bayQuantityGoodsSum);

                } else if (orderDto.getOrderType() == OrderType.OT_103.getCode() && slkjOrderPricingSnapshot.getBayQuantity() != null) {
                    //混合订单
                    if (slkjOrderPricingSnapshot.getItemType().equals("TICKET")) {
                        //混合订单中的票类订单
                        // slkjOrderPricingSnapshot.setTicketCategoryName(slkjOrderPricingSnapshot.getTicketCategoryName() + "*" + slkjOrderPricingSnapshot.getBayQuantity());
                        slkjOrderPricingSnapshot.setTicketCategoryName(slkjOrderPricingSnapshot.getTicketCategoryName());
                        bayQuantitySum += slkjOrderPricingSnapshot.getBayQuantity();
                        orderDto.setBayQuantitySum(bayQuantitySum);

                    } else {
                        //混合订单中的商品订单
                        // slkjOrderPricingSnapshot.setGoodsName(slkjOrderPricingSnapshot.getGoodsName() + "*" + slkjOrderPricingSnapshot.getBayQuantity());
                        slkjOrderPricingSnapshot.setGoodsName(slkjOrderPricingSnapshot.getGoodsName());
                        bayQuantityGoodsSum += slkjOrderPricingSnapshot.getBayQuantity();
                        orderDto.setBayQuantityGoodsSum(bayQuantityGoodsSum);
                    }


                }

            }

            List<SlkjOrderSplitSnapshotDto> slkjOrderSplitSnapshot = orderDto.getSlkjOrderSplitSnapshot();
//          如果是投资人名称 去除赋值到字段中
            for (SlkjOrderSplitSnapshotDto orderSplitSnapshot : slkjOrderSplitSnapshot) {

                if (SlkjOrderSplitSnapshotDto.INVESTOR.equals(orderSplitSnapshot.getRelatedType())) {
                    String otherFields = orderSplitSnapshot.getOtherFields();
                    JSONObject jsonObject = JSON.parseObject(otherFields);
                    Object investorName = jsonObject.get("investorName");
                    orderSplitSnapshot.setInvestorName(investorName.toString());
                }
            }


            // 使用 BeanUtils 进行深拷贝 金额转化为元给前端
            ModelMapper modelMapper = new ModelMapper();
            OrderDetailVo orderDetailVo = modelMapper.map(orderDto, OrderDetailVo.class);
            orderDetailVos.add(orderDetailVo);
        }

        PageInfo pageInfo = new PageInfo<>(orderDtos);
        pageInfo.setList(orderDetailVos);

        return pageInfo;
    }

    /**
     * 查询订单列表
     *
     * @param slkjOrder 订单
     * @return 订单
     */
    @Override
    public List<SlkjOrder> selectSlkjOrderList(SlkjOrder slkjOrder) {
        return slkjOrderMapper.selectSlkjOrderList(slkjOrder);
    }

    @Override
    public List<SlkjOrder> selectSlkjOrderList(QueryOrderExport queryOrderExport) {
        return slkjOrderMapper.selectSlkjOrderList(queryOrderExport);
    }

    /**
     * 修改订单
     *
     * @param slkjOrder 订单
     * @return 结果
     */
    @Override
    public int updateSlkjOrder(SlkjOrder slkjOrder) {
        slkjOrder.setUpdateTime(DateUtils.getNowDate());
        return slkjOrderMapper.updateSlkjOrder(slkjOrder);
    }

    /**
     * 批量删除订单
     *
     * @param orderIds 需要删除的订单主键
     * @return 结果
     */
    @Override
    public int deleteSlkjOrderByOrderIds(Long[] orderIds) {
        return slkjOrderMapper.deleteSlkjOrderByOrderIds(orderIds);
    }

    @SuppressWarnings("resource")
    @Override
    public PageInfo<PosOrderVoV2> posOrdersV2(PosOrderQueryVo queryParam, boolean paginate) {
        Stopwatch stopwatch = Stopwatch.createStarted();
        Page<Object> page = PageUtils.startPageExt(paginate);
        List<SlkjOrder> orders = slkjOrderMapper.selectPosOrderList(queryParam);
        if (CollectionUtils.isEmpty(orders)) {
            log.info("门店 [{}] 暂无订单！", queryParam.getShopId());
            return new PageInfo<>(Lists.newArrayList());
        }
        long total = page.getTotal();

        List<Long> orderIds = orders.stream().map(SlkjOrder::getOrderId).collect(Collectors.toList());

        // 获取操作记录
        Map<Long, List<SlkjOrderStatusLog>> listMap = slkjOrderStatusLogMapper.findByOrderIds(orderIds).stream().collect(Collectors.groupingBy(SlkjOrderStatusLog::getOrderId));

        // 获取订单明细
        List<SlkjOrderPricingSnapshot> pricingSnapshots = slkjOrderPricingSnapshotMapper.selectByOrderIds(orderIds);
        Map<Long, List<SlkjOrderPricingSnapshot>> snapMap = pricingSnapshots.stream().collect(Collectors.groupingBy(SlkjOrderPricingSnapshot::getOrderId));

        // 获取所有商品
        Map<Long, String> goodsMap = null;
        Set<Long> goodsIds = pricingSnapshots.stream().filter(snap -> "GOODS".equals(snap.getItemType())).map(SlkjOrderPricingSnapshot::getGoodsId).collect(Collectors.toSet());
        if (CollectionUtils.isNotEmpty(goodsIds)) {
            goodsMap = slkjProductMapper.selectProductByProductIds(Lists.newArrayList(goodsIds)).stream().collect(Collectors.toMap(SlkjProduct::getProductId, SlkjProduct::getProductImg));
        }

        // 获取项目
        Map<Long, String> projectMap = null;
        Set<Long> projectIds = orders.stream().map(SlkjOrder::getProjectId).collect(Collectors.toSet());
        if (CollectionUtils.isNotEmpty(projectIds)) {
            projectMap = projectMapper.selectProjectByIdList(Lists.newArrayList(projectIds)).stream().collect(Collectors.toMap(Project::getProjectId, Project::getCover));
        }

        final List<PosOrderVoV2> result = new ArrayList<>();
        PosOrderVoV2 pov;
        PosOrderVoV2.Ticket ticket;
        PosOrderVoV2.Goods goods;
        PosOrderVoV2.OperationRecord record;

        // 组装数据
        for (SlkjOrder order : orders) {
            pov = new PosOrderVoV2();
            pov.setOrderId(order.getOrderId());
            pov.setOrderNumber(order.getOrderNumber());
            pov.setCreateTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, order.getCreateTime()));
            pov.setSource(order.getSource());
            pov.setOrderType(order.getOrderType());
            pov.setActualAmount(MoneyUtils.fen2Yuan(order.getActualAmount()));
            pov.setPaymentType(order.getPaymentType());
            pov.setTicketStatus(order.getBusinessStatus());
            pov.setGoodsStatus(order.getGoodsStatus());
            pov.setCover("");
            if (Objects.nonNull(projectMap) && projectMap.containsKey(order.getProjectId())) {
                pov.setCover(projectMap.get(order.getProjectId()));
            }
            pov.setProjectName(order.getProjectName());

            pov.setCashier(order.getCreateBy());
            OrderSource os = OrderSource.fromCode(order.getSource());
            // 如果是小程序，则显示渠道名称，只有门店显示当前收银员
            if (!os.equals(OrderSource.SHOP)) {
                pov.setCashier(os.getDescription());
            }

            // 明细
            List<PosOrderVoV2.Ticket> tickets = new ArrayList<>();
            List<PosOrderVoV2.Goods> goodsList = new ArrayList<>();
            if (snapMap.containsKey(order.getOrderId())) {
                for (SlkjOrderPricingSnapshot snap : snapMap.get(order.getOrderId())) {
                    String itemType = snap.getItemType();
                    if ("GOODS".equals(itemType)) {
                        // 商品
                        if (Objects.nonNull(goodsMap) && goodsMap.containsKey(snap.getGoodsId())) {
                            goods = new PosOrderVoV2.Goods();
                            goods.setName(snap.getGoodsName());
                            goods.setItemUrl(goodsMap.get(snap.getGoodsId()));
                            goods.setBayQuantity(snap.getBayQuantity());
                            goods.setPrice(MoneyUtils.fen2Yuan(snap.getUserActualAmount()));
                            goodsList.add(goods);
                        } else {
                            log.warn("订单 [{}] 商品 [{}] 信息不存在！", snap.getOrderId(), snap.getGoodsId());
                        }
                    } else {
                        // 票
                        ticket = new PosOrderVoV2.Ticket();
                        ticket.setName(snap.getTicketCategoryName());
                        ticket.setItemUrl(pov.getCover());
                        ticket.setBayQuantity(snap.getBayQuantity());
                        ticket.setPrice(MoneyUtils.fen2Yuan(snap.getUserActualAmount()));
                        tickets.add(ticket);
                    }
                }
            }
            pov.setTickets(tickets);
            pov.setGoods(goodsList);

            // 操作记录
            List<PosOrderVoV2.OperationRecord> operationRecords = new ArrayList<>();
            if (listMap.containsKey(order.getOrderId())) {
                List<SlkjOrderStatusLog> logs = listMap.get(order.getOrderId());
                for (SlkjOrderStatusLog log : logs) {
                    OrderBusinessStatus businessStatus = OrderBusinessStatus.fromCode(log.getStatus());
                    record = new PosOrderVoV2.OperationRecord();
                    String content;
                    // 处理特定业务状态的操作记录
                    if (businessStatus == OrderBusinessStatus.UNREDEEMED) {
                        // 订单来自第三方渠道的待核销状态
                        PosOrderVoV2.OperationRecord ord = new PosOrderVoV2.OperationRecord();
                        ord.setOperationAccount(OrderSource.fromCode(order.getSource()).getDescription());
                        ord.setOperationTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, order.getCreateTime()));
                        String msg = "结账：收款金额 ¥" + MoneyUtils.fen2Yuan(order.getActualAmount()) + "（" + LakalaPaymentTypeEnum.fromCode(order.getPaymentType()).getDescription() + "）";
                        ord.setContent(msg);
                        operationRecords.add(ord);

                        content = OrderBusinessStatus.UNREDEEMED.getDescription();
                    } else if (businessStatus == OrderBusinessStatus.REDEEMED && order.getSource().equals(OrderSource.SHOP.getCode())) {
                        // 门店订单，支付成功后状态为已核销，但没有操作记录，需要特殊处理
                        PosOrderVoV2.OperationRecord or = new PosOrderVoV2.OperationRecord();
                        or.setOperationAccount(StringUtils.isBlank(log.getUpdateBy()) ? "系统" : log.getUpdateBy());
                        or.setOperationTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, log.getChangeTime()));
                        String desc = "结账：收款金额 ¥" + MoneyUtils.fen2Yuan(order.getActualAmount()) + "（" + LakalaPaymentTypeEnum.fromCode(order.getPaymentType()).getDescription() + "）";
                        or.setContent(desc);
                        operationRecords.add(or);

                        content = OrderBusinessStatus.REDEEMED.getDescription();
                    } else {
                        // 处理其他业务状态
                        content = generateContentForOtherStatuses(businessStatus, order);
                    }

                    // 设置通用操作记录属性
                    record.setContent(content);
                    record.setOperationAccount(StringUtils.isBlank(log.getUpdateBy()) ? "系统" : log.getUpdateBy());
                    if (!os.equals(OrderSource.SHOP)) {
                        record.setOperationAccount(os.getDescription());
                    }
                    record.setOperationTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, log.getChangeTime()));
                    operationRecords.add(record);
                }
            }
            pov.setOperationRecords(operationRecords);
            result.add(pov);
        }

        log.info("pos订单列表数据获取共耗时：{}", stopwatch.stop());
        PageInfo<PosOrderVoV2> pageInfo = new PageInfo<>(result);
        pageInfo.setTotal(total);
        pageInfo.setPageNum(page.getPageNum());
        pageInfo.setPageSize(page.getPageSize());
        return pageInfo;
    }

    private String generateContentForOtherStatuses(OrderBusinessStatus businessStatus, SlkjOrder order) {
        switch (businessStatus) {
            case PENDING_PAYMENT:
                return "结账：支付金额 ¥" + MoneyUtils.fen2Yuan(order.getActualAmount());
            case ORDER_CANCELLED:
                return OrderBusinessStatus.ORDER_CANCELLED.getDescription();
            case REFUNDED:
                return "退款：退款金额 ¥" + MoneyUtils.fen2Yuan(order.getActualAmount());
            case WRISTBAND_RECEIVED:
                return OrderBusinessStatus.WRISTBAND_RECEIVED.getDescription();
            case DEVICE_RECEIVED:
                return OrderBusinessStatus.DEVICE_RECEIVED.getDescription();
            case WAITING_FOR_PICKUP:
                return OrderBusinessStatus.WAITING_FOR_PICKUP.getDescription();
            case WAITING_FOR_SHIPPING:
                return OrderBusinessStatus.WAITING_FOR_SHIPPING.getDescription();
            case SHIPPED:
                return OrderBusinessStatus.SHIPPED.getDescription();
            default:
                return OrderBusinessStatus.COMPLETED.getDescription();
        }
    }

    @Override
    public List<DetailsVo> details(Date startTime, Date endTime, Long shopId) {
        List<SlkjOrder> slkjOrders = slkjOrderMapper.selectSlkjOrder(startTime, shopId, endTime);
        Map<String, DetailsVo> detailsVoMap = new HashMap<>();
        DetailsVo detailsVo = null;
        for (SlkjOrder order : slkjOrders) {
            if (order.getOrderType().equals(OrderType.OT_102.getCode())) {
                List<SlkjOrderPricingSnapshot> snapshots = slkjOrderPricingSnapshotMapper.selectByOrderIdList(order.getOrderId());
                for (SlkjOrderPricingSnapshot snapshot : snapshots) {
                    if (snapshot.getItemType().equals(SnapshotItemType.GOODS.getCode())) {
                        detailsVo.setGoodsIncome(new BigDecimal(MoneyUtils.fen2Yuan(snapshot.getUserActualAmount())));
                        detailsVo.setGoodsNum(detailsVo.getGoodsNum() + 1);
                    }
                }
            }
            if (order.getBusinessStatus() != null && order.getBusinessStatus().equals(OrderBusinessStatus.DEVICE_RECEIVED.getCode())
                    && order.getPaymentStatus().equals(LakalaTradeStateEnum.SUCCESS.name()) ||
                    (order.getBusinessStatus() != null && order.getBusinessStatus().equals(OrderBusinessStatus.COMPLETED.getCode()))) {
                LocalDate orderDate = order.getCreateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                String key = orderDate + "-" + order.getShopName();

                detailsVo = detailsVoMap.get(key);
                if (detailsVo == null) {
                    detailsVo = new DetailsVo();
                    detailsVo.setOrderDate(order.getCreateTime());
                    detailsVo.setShopName(order.getShopName());
                    detailsVoMap.put(key, detailsVo);
                }

                // 获取分账金额
                List<SlkjOrderSplitSnapshot> snapshots = slkjOrderSplitSnapshotMapper.selectByOrderId(order.getOrderId());
                BigDecimal investIncome = BigDecimal.ZERO;
                BigDecimal ticketSystemIncome = BigDecimal.ZERO;
                BigDecimal operatorIncome = BigDecimal.ZERO;
                BigDecimal projectIncome = BigDecimal.ZERO;
                for (SlkjOrderSplitSnapshot snapshot : snapshots) {
                    BigDecimal splitAmount = getSplitAmount(order.getOrderId(), snapshot.getRelatedType());
                    switch (snapshot.getRelatedType()) {
                        case "INVESTOR":
                            investIncome = investIncome.add(splitAmount);
                            break;
                        case "PROJECT":
                            projectIncome = projectIncome.add(splitAmount);
                            break;
                        case "TICKET_SYSTEM":
                            ticketSystemIncome = ticketSystemIncome.add(splitAmount);
                            break;
                        case "OPERATION":
                            operatorIncome = operatorIncome.add(splitAmount);
                            break;
                        default:
                            // 不做处理
                            break;
                    }
                }

                // 更新分账金额
                detailsVo.setInvestIncome(detailsVo.getInvestIncome().add(investIncome));
                detailsVo.setProgectIncome(detailsVo.getProgectIncome().add(projectIncome));
                detailsVo.setTicketSystemIncome(detailsVo.getTicketSystemIncome().add(ticketSystemIncome));
                detailsVo.setOperatorIncome(detailsVo.getOperatorIncome().add(operatorIncome));

                // 更新分账总金额
                BigDecimal splitIncome = investIncome.add(projectIncome).add(ticketSystemIncome).add(operatorIncome);
                detailsVo.setSplitIncome((detailsVo.getSplitIncome().add(splitIncome)));

                // 获取订单详情
                List<SlkjOrderPricingSnapshot> snapshots1 = slkjOrderPricingSnapshotMapper.selectByOrderId(order.getOrderId());
                for (SlkjOrderPricingSnapshot pricingSnapshot : snapshots1) {
                    BigDecimal userActualAmount = BigDecimal.valueOf(pricingSnapshot.getUserActualAmount()).divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_UP);

                    detailsVo.setTotalIncome(detailsVo.getTotalIncome().add(userActualAmount));
                    if (pricingSnapshot.getItemType().equals(SnapshotItemType.TICKET.getCode())) {
                        detailsVo.setTicketIncome(detailsVo.getTicketIncome().add(userActualAmount));
                        detailsVo.setTicketNum(detailsVo.getTicketNum() + pricingSnapshot.getQuantity() * pricingSnapshot.getBayQuantity());
                    } else {
                        detailsVo.setGoodsNum(detailsVo.getGoodsNum() + pricingSnapshot.getQuantity() * pricingSnapshot.getBayQuantity());
                        detailsVo.setGoodsIncome(detailsVo.getGoodsIncome().add(userActualAmount));
                    }
                }
            }
        }

        List<DetailsVo> sortedDetailsVoList = detailsVoMap.values().stream().sorted(Comparator.comparing(DetailsVo::getOrderDate).reversed()).collect(Collectors.toList());

        return sortedDetailsVoList;
    }

    private BigDecimal getSplitAmount(Long orderId, String relatedType) {
        BigDecimal amount = BigDecimal.ZERO;
        List<SlkjOrderSplitSnapshot> snapshots = slkjOrderSplitSnapshotMapper.selectByOrderId(orderId);
        for (SlkjOrderSplitSnapshot snapshot : snapshots) {
            if (snapshot.getRelatedType().equals(relatedType) && snapshot.getProfitShareAmount() != null) {
                amount = amount.add(new BigDecimal(snapshot.getProfitShareAmount())).divide(BigDecimal.valueOf(10000), 4, RoundingMode.HALF_UP);
            }
        }
        return amount;
    }
}
